package com.changgou.seckill.service.impl;

import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.dao.SeckillOrderMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.service.SeckillOrderService;
import com.changgou.seckill.task.MultiThreadingCreateOrder;
import entity.IdWorker;
import entity.SeckillStatus;
import entity.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * @author:hushengjin
 * @date:2019-08-12 20:49:32
 */
@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private MultiThreadingCreateOrder multiThreadingCreateOrder;

    /**
     * 添加秒杀商品
     *
     * @param time
     * @param id
     * @param username
     * @return
     */
    @Override
    public Boolean add(String time, Long id, String username) {
        //递增,判断是否排队
        Long count = redisTemplate.boundHashOps("UserQueueCount").increment(username, 1);
        if (count > 1) {
            //20005:表示有重复抢单
            throw new RuntimeException(String.valueOf(StatusCode.REPERROR));
        }
        //排队信息封装
        SeckillStatus seckillStatus = new SeckillStatus(username,new Date(),1,id,time);
        //将秒杀信息存入redis中
        redisTemplate.boundListOps("SeckillOrderQueue").leftPush(seckillStatus);
        //将抢单状态存入redis中
        redisTemplate.boundHashOps("UserQueueStatus").put(username, seckillStatus);
        //多线程操作
        multiThreadingCreateOrder.createOrder();

        return true;
    }

    /**
     * 抢单状态查询
     *
     * @param username
     * @return
     */
    @Override
    public SeckillStatus queryStatus(String username) {
        return (SeckillStatus) redisTemplate.boundHashOps("UserQueueStatus").get(username);
    }

    /**
     * 更新订单状态
     *
     * @param out_trade_no
     * @param transaction_id
     * @param username
     */
    @Override
    public void updatePayStatus(String out_trade_no, String transaction_id, String username) {
        //订单数据从数据库中查询出来
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);
        if (seckillOrder != null) {
            //修改状态
            seckillOrder.setStatus("1"); // 1 已支付
            //支付时间
            seckillOrder.setPayTime(new Date());
            //同步到Mysql
            seckillOrderMapper.insertSelective(seckillOrder);
            //清空redis缓存
            redisTemplate.boundHashOps("SeckillOrder").delete(username);
            //清空用户排队数据
            redisTemplate.boundHashOps("UserQueueCount").delete(username);
            //删除抢购状态数据
            redisTemplate.boundHashOps("UserQueueStatus").delete(username);
        }
    }

    /**
     * 关闭订单,回滚数据
     *
     * @param username
     */
    @Override
    public void closeOrder(String username) {
        //将消息转换成seckillStatus
        SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundHashOps("UserQueueStatus").get(username);
        //获取redis中的订单数据
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);
        //如果redis中有用户订单数据,说明未支付
        if (seckillStatus != null && seckillOrder != null) {
            //删除订单
            redisTemplate.boundHashOps("SeckillOrder").delete(username);
            //回滚数据库
            //1)从redis中获取该商品
            SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + seckillStatus.getTime()).get(seckillStatus.getGoodsId());
            //2)如果redis中没有,从数据库中加载
            if (seckillGoods == null) {
                seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillStatus.getGoodsId());
            }
            //3)数量加一(递增数量+1, 队列数量+1)
            redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillGoods.getId()).leftPush(seckillGoods.getId());
            redisTemplate.boundHashOps("SeckillGoodsCount").increment(seckillGoods.getId(), 1);
            //4)同步到redis中
            redisTemplate.boundHashOps("SeckillGoods_" + seckillStatus.getTime()).put(seckillGoods.getId(), seckillGoods);
            //清理排队标识
            redisTemplate.boundHashOps("UserQueueCount").delete(username);
            //清理抢单标识
            redisTemplate.boundHashOps("UserQueueStatus").delete(username);
        }
    }

}
